package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.autoconfig.templates.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.CommentApi;
import com.tanhua.dubbo.api.MovementsApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.mongo.Comment;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class MovementsService {

    //注入对应的接口
    @DubboReference
    private MovementsApi movementsApi;
    @DubboReference
    private UserInfoApi userInfoApi;
    @Autowired
    private OssTemplate ossTemplate;
    @Autowired
    private StringRedisTemplate template;//专门处理字符串数据
    @DubboReference
    private CommentApi commentApi;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private MqMessageService mqMessageService;


    //发布动态方法
    public void movements(String textContent, MultipartFile imageContent[], String location, String longitude, String latitude) throws IOException {
        //1.获取当前用户id,为动态发布人
        Long userId = UserHolder.getUserId();
        //2.依次向动态对象中设置值
        Movement movement = new Movement();
        movement.setUserId(userId);         //动态发布人
        movement.setTextContent(textContent);//文字动态
        movement.setCreated(System.currentTimeMillis());//发布时间
        movement.setLongitude(longitude);   //经度
        movement.setLatitude(latitude);     //纬度
        movement.setLocationName(location); //位置
        //3.将前端传递的图片上传到阿里云
        List<String> medias = new ArrayList<>();
        for (MultipartFile image : imageContent) {
            //将图片上传到阿里云以后获取到图片的地址
            String url = ossTemplate.upload(image.getInputStream(), image.getOriginalFilename());
            //将图片的地址添加到集合当中
            medias.add(url);
        }
        //4.将图片设置对象当中去
        movement.setMedias(medias);
        //5.调用api保存
        String id = movementsApi.save(movement);
        //String类型的id
        mqMessageService.sendAudiMessage(id);
    }

    //查询自己的动态
    public PageResult all(Integer page, Integer pagesize, Long userId) {

        //1.根据用户id查询出用户的所有动态
        List<Movement> list = movementsApi.findByUserId(page, pagesize, userId);
        //2.判断动态集合是否为空
        if (CollUtil.isEmpty(list)) {
            //3.如果为空就返回一个空的分页对象
            return new PageResult();
        }
        //4.构建一个新的动态返回对象的集合（因为是多条动态）
        //5.根据userId查询出对应的用户信息
        UserInfo info = userInfoApi.findById(userId);
        List<MovementsVo> vos = new ArrayList<>();
        //6.循环vos构建每一个对象
        for (Movement movement : list) {
            //使用构造方法进行构造
            MovementsVo vo = MovementsVo.init(info, movement);
            //从redis中查询点赞状态
            String redisKey = Constants.MOVEMENTS_INTERACT_KEY + vo.getId();
            String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
            Boolean hasKey = redisTemplate.opsForHash().hasKey(redisKey, hashKey);
            //进行判断
            if (hasKey) {
                vo.setHasLiked(1);
            }

            String loveKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
            Boolean hasLoveKey = redisTemplate.opsForHash().hasKey(redisKey, loveKey);
            if (hasLoveKey) {
                vo.setHasLoved(1);
            }
            //将构造好的对象添加到vos当中
            vos.add(vo);
        }
        //7.返回该分页对象
        return new PageResult(page, pagesize, 0l, vos);
    }

    //查询好友动态
    public PageResult findByFriendId(Integer page, Integer pagesize) {
        //1.获取到当前用户的id
        Long friendId = UserHolder.getUserId();
        //2.根据当前用户的id查询好友关系表
        List<Movement> list = movementsApi.findByFriendId(friendId, page, pagesize);
        //3.这里使用公共的方法生成了一个返回的对象
        return initPage(list, page, pagesize);
    }

    //查询推荐的动态
    public PageResult findByRecommend(Integer page, Integer pagesize) {
        //1.获取当前用户id
        Long userId = UserHolder.getUserId();
        //2.从redis中查询到推荐的动态id集合
        String key = "MOVEMENTS_RECOMMEND_" + userId;
        String value = template.opsForValue().get(key);
        //3.判断数据是否存在
        List<Movement> list = new ArrayList<>();
        if (!StringUtils.isEmpty(value)) {
            //4.如果存在,获取数据中的所有id,调用API根据动态的id列表,查询出对应的动态详情
            String[] movementIds = value.split(",");
            list = movementsApi.findByIds(movementIds, page, pagesize);
        } else {
            //5.如果数据不存在,调用API随机查询动态列表
            list = movementsApi.RandomMovement(pagesize);//随机十条
        }
        //6.调用公共方法,构造返回数据
        return initPage(list, page, pagesize);
    }

    //公共的方法
    private PageResult initPage(List<Movement> list, Integer page, Integer pagesize) {
        //3、判断动态列表是否为空
        if (CollUtil.isEmpty(list)) {
            return new PageResult();
        }
        //一次性，将list中所有的动态发布人查询出来
        //a：提取list中的所有动态发布人id
        List<Long> userIds = CollUtil.getFieldValues(list, "userId", Long.class);//list，属性名，类型
        //b：调用UserInfoApi，查询多个用户的用户信息
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds);
        //4、循环List<Movement>，一个Movement构建一个MovementVo对象
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement movement : list) {
            Long userId = movement.getUserId();//获取动态发布人
            UserInfo info = map.get(userId); //直接从map获取
            //UserInfo info = userInfoApi.findById(userId);//查询动态发布人的信息
            //调用MovementsVo工具方法init构建
            MovementsVo vo = MovementsVo.init(info, movement);//用户信息，动态详情
            //从redis中查询点赞状态
            String redisKey = Constants.MOVEMENTS_INTERACT_KEY + vo.getId();
            String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
            Boolean hasKey = redisTemplate.opsForHash().hasKey(redisKey, hashKey);
            //进行判断
            if (hasKey) {
                vo.setHasLiked(1);
            }

            String loveKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
            Boolean hasLoveKey = redisTemplate.opsForHash().hasKey(redisKey, loveKey);
            if (hasLoveKey) {
                vo.setHasLoved(1);
            }
            vos.add(vo);
        }
        //5、返回
        return new PageResult(page, pagesize, 0l, vos);
    }

    //根据id查询
    public MovementsVo findById(String id) {
        //1.根据id调用API查询动态详情
        Movement movement = movementsApi.findById(id);
        //2.获取动态发布人
        Long userId = movement.getUserId();
        //3.根据当前用户查询到动态发布人
        UserInfo userInfo = userInfoApi.findById(userId);
        //4.构造返回对象
        return MovementsVo.init(userInfo, movement);
    }

    //点赞
    public Integer like(String movementId) {
        //1.根据动态id进行点赞
        Integer commentType = 1;
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(commentType);
        comment.setContent(null);
        comment.setUserId(UserHolder.getUserId());
        comment.setCreated(System.currentTimeMillis());
        //2.调用api进行保存
        Integer count = commentApi.save(comment);
        String redisKey = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(redisKey, hashKey, "1");

        //在业务完成以后想rabbitMq发送消息
        mqMessageService.sendLogMessage(UserHolder.getUserId(),"0203","log.movement",movementId);
        return count;
    }

    //喜欢
    public Integer love(String movementId) {
        //1.根据动态id进行喜欢
        Integer commentType = 3;
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(commentType);
        comment.setContent(null);
        comment.setUserId(UserHolder.getUserId());
        comment.setCreated(System.currentTimeMillis());
        //2.调用api进行保存
        Integer count = commentApi.save(comment);
        String redisKey = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(redisKey, hashKey, "1");
        return count;
    }

    //取消点赞
    public Integer dislike(String movementId) {
        //1.知道互动类型为1
        Integer commentType = 1;
        //2.获取到动态id
        //3.获取到操作用户id
        Long userId = UserHolder.getUserId();
        //4.将数据库中的互动信息进行删除
        Integer count = commentApi.delete(userId, movementId, commentType);
        //5.删除redis中保存的点赞标识
        String redisKey = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hasKey = Constants.MOVEMENT_LIKE_HASHKEY + userId;
        redisTemplate.opsForHash().delete(redisKey, hasKey);
        //6.返回
        return count;
    }

    //取消喜欢
    public Integer unlove(String movementId) {
        //1.已经知道动态id，删除数据库中的互动信息
        Long userId = UserHolder.getUserId();
        Integer commentType = 3;
        Integer count = commentApi.delete(userId, movementId, commentType);
        //2.删除redis中存储的喜欢标识
        String redisKey=Constants.MOVEMENTS_INTERACT_KEY +movementId;
        String hasKey =Constants.MOVEMENT_LOVE_HASHKEY + userId;
        redisTemplate.opsForHash().delete(redisKey,hasKey);
        //3.返回参数
        return count;
    }
}
